﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Engine.Graphics;
using Microsoft.Xna.Framework.Input;

namespace Engine
{
    public class UIScreen : UIElement
    {
        public Texture2D background;
        protected ScreenManager manager;

        public UIScreen() : base(Vector2.Zero)
        {

        }

        public void SetScreenManager(ScreenManager _manager)
        {
            manager = _manager;
        }

        public virtual void Show()
        {
            IsActive = true;
        }

        public virtual void Hide()
        {
            IsActive = false;
        }

        public override void Draw()
        {
            if (!IsActive)
                return;
            if (background != null)
            {
                Size = new Vector2(background.Width, background.Height);
                GraphicsEngine.Instance.DrawGUITexture(background, ElementRect, null, Color.White, 1);
            }
            base.Draw();
        }
    }

    public class UITextField : UIElement
    {
        public event UIEvent OnEnterDown; 
        public bool HasFocus = false;
        public string Text;

        const float BLINK_TIME = 0.4f;
        float blinkTimer = BLINK_TIME;
        bool blinkOn = true;
        int cursorPos = 0;

        public UITextField(string _text, Vector2 _position, Vector2 _size)
            : base(_position)
        {
            Text = _text;
            cursorPos = Text.Length;
            Size = _size;
            EventInput.CharEntered += new CharEnteredHandler(HandleCharEntered);
        }

        void HandleCharEntered(object sender, CharacterEventArgs e)
        {
            if (!HasFocus || e.Character == '\b' || e.Character == '	')
                return;
            Text = Text.Insert(cursorPos, ""+e.Character);
            cursorPos++;
        }

        public override void Update(GameTime _gameTime)
        {
            if (!IsActive)
                return;
            base.Update(_gameTime);

            blinkTimer -= (float)_gameTime.ElapsedGameTime.TotalSeconds;
            if(blinkTimer <= 0)
            {
                blinkTimer = BLINK_TIME;
                blinkOn = !blinkOn;
            }

            if (InputHandler.LeftMouseClicked())
            {
                if (ElementRect.Contains(MathUtils.Vector2ToPoint(InputHandler.MousePosition)))
                    HasFocus = true;
                else
                    HasFocus = false;
            }


            if (HasFocus)
            {
                if (InputHandler.KeyPressed(Keys.Enter))
                    if (OnEnterDown != null)
                        OnEnterDown(this, Text);

                if (InputHandler.KeyPressed(Keys.Back) && Text.Length > 0 && cursorPos > 0)
                {
                    Text = Text.Remove(cursorPos - 1, 1);
                    cursorPos--;
                    cursorPos = Math.Min(cursorPos, Text.Length+1);
                }

                if (InputHandler.KeyPressed(Keys.Left))
                {
                    cursorPos--;
                    cursorPos = Math.Max(cursorPos, 0);
                }

                if (InputHandler.KeyPressed(Keys.Right))
                {
                    cursorPos++;
                    cursorPos = Math.Min(cursorPos, Text.Length);
                }
            }
        }

        public override void Draw()
        {
            if (!IsActive)
                return;
            base.Draw();

            GraphicsEngine.Instance.DrawGUITexture(GraphicsEngine.Instance.emptyTexture, new Rectangle((int)Position.X, (int)Position.Y, (int)Size.X, (int)Size.Y), null, Color.Gray, 0.1f);
            GraphicsEngine.Instance.DrawRectangle(new Rectangle((int)Position.X, (int)Position.Y, (int)Size.X, (int)Size.Y), 5, Color.Black, 0.05f);
            GraphicsEngine.Instance.DrawString(Text, Position, Color.Black, TextAlignement.Left, 0);
            if(HasFocus && blinkOn)
            {
                int textLength = 3;
                if(Text.Length > 0)
                    textLength = (int)GraphicsEngine.Instance.GetFont("SmallFont").MeasureString(Text.Substring(0, cursorPos)).X;
                Vector2 start = Position +  new Vector2(textLength + 3, 5);
                Vector2 end = start + new Vector2(0, Size.Y - 5);
                GraphicsEngine.Instance.DrawLine(start, end, 3, Color.Black);
            }
        }
    }

    /*public class UITimeLine : UIElement
    {
        public event UIEvent OnMouseDown;
        public Texture2D markerTexture;
        public float startValue;
        public float endValue;
        public float markerPos;
        public float fixedMarkerIntervallSmall = 0.025f;
        public float fixedMarkerIntervallBig;

        public List<float> additionalMarkers;

        public UITimeLine()
        {
            additionalMarkers = new List<float>();
            fixedMarkerIntervallBig = fixedMarkerIntervallSmall * 4;
        }

        public override void Update(GameTime _gameTime)
        {
            if (InputHandler.LeftMouseClicked() && ElementRect.Contains((int)InputHandler.MousePosition.X, (int)InputHandler.MousePosition.Y))
            {
                markerPos = (InputHandler.MousePosition.X - Position.X) / (Size.X);
                if ((markerPos % fixedMarkerIntervallSmall) < fixedMarkerIntervallSmall / 5 || (markerPos % fixedMarkerIntervallSmall) > fixedMarkerIntervallSmall - fixedMarkerIntervallSmall / 5)
                    markerPos = fixedMarkerIntervallSmall * (int)Math.Round(markerPos / fixedMarkerIntervallSmall);
                if (OnMouseDown != null)
                    OnMouseDown(this, markerPos);
            }
            base.Update(_gameTime);
        }

        public override void Draw(SpriteBatch _spriteBatch)
        {
            foreach (float marker in additionalMarkers)
                _spriteBatch.Draw(markerTexture, Position + new Vector2(Size.X * ((marker - startValue) / (endValue - startValue)) - markerTexture.Width / 2, 0), null, Color.Blue,
                    0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0.9f);

            float drawPos = 0;
            while (drawPos <= 1)
            {
                float posY = Size.Y/2;
                float scaleY = 0.5f;
                if ((decimal)drawPos % (decimal)fixedMarkerIntervallBig == 0)
                {
                    posY = Size.Y / 4;
                    scaleY = 0.75f;
                }
                _spriteBatch.Draw(markerTexture, Position + new Vector2(Size.X * drawPos - markerTexture.Width / 2, posY), null, Color.Black,
                    0, Vector2.Zero, new Vector2(0.5f, scaleY), SpriteEffects.None, 0.95f);
                drawPos += fixedMarkerIntervallSmall;
                drawPos = (float)Math.Round(drawPos, 3);
            }

            _spriteBatch.Draw(markerTexture, Position + new Vector2(Size.X * ((markerPos - startValue) / (endValue - startValue)) - markerTexture.Width / 2, 0), Color.Red);
            base.Draw(_spriteBatch);
        }        
    }*/

    public class UILabel : UIElement
    {
        public string Text;
        string font;
        public UILabel(string _text, Vector2 _pos, string _spriteFont = "SmallFont") : base(_pos)
        {
            Text = _text;
            font = _spriteFont;
        }

        public override void Draw()
        {
            if (!IsActive)
                return;
            base.Draw();
            Graphics.GraphicsEngine.Instance.DrawString(GraphicsEngine.Instance.GetFont(font), Text, Position, Color.Black, TextAlignement.Left);
        }
    }

    public class UIToggleGroup : UIElement
    {

        public UIToggleGroup()
            : base(Vector2.Zero)
        {

        }

        List<UIToggleButton> buttons = new List<UIToggleButton>();
        public int ActiveIndex { get; private set; }

        public void AddToogleButton(UIToggleButton _button)
        {
            _button.ButtonPressed += new UIEvent(_button_ButtonPressed);
            if (buttons.Count == 0)
            {
                ActiveIndex = 0;
                _button.IsDown = true;
            }
            buttons.Add(_button);
            Childs.Add(_button);
        }

        public void SetActive(int _index)
        {
            if (_index < buttons.Count && _index >= 0)
            {
                ActiveIndex = _index;
                for (int i = 0; i < buttons.Count; i++)
                {
                    buttons[i].IsDown = i == _index;
                }
            }
        }

        void _button_ButtonPressed(UIElement _sender, object _message)
        {
            if (!(bool)_message)
                (_sender as UIToggleButton).IsDown = true;

            SetActive(buttons.IndexOf(_sender as UIToggleButton));
        }
    }

    public class UIToggleButton : UIButton
    {
        public UIToggleButton(string _text, string _upTexture, string _downTexture, Vector2 _relativePosition) : base(_text, _upTexture, _downTexture, _relativePosition)
        {
        }

        public UIToggleButton(string _text, string _upTexture, string _downTexture, Vector2 _relativePosition, Vector2 _size)
            : base(_text, _upTexture, _downTexture, _relativePosition, _size)
        {
        }

        public UIToggleButton(string _text, Texture2D _upTexture, Texture2D _downTexture, Vector2 _relativePosition, Vector2 _size)
            : base(_text, _upTexture, _downTexture, _relativePosition, _size)
        {
        }

        public override void Update(GameTime _gameTime)
        {
            if (ElementRect.Contains((int)InputHandler.MousePosition.X, (int)InputHandler.MousePosition.Y))
            {
                if (InputHandler.LeftMouseClicked())
                {
                    IsDown = !IsDown;
                    FireButtonPressed(this, IsDown);
                }
            }
        }
    }

    public class UIElement
    {
        public delegate void UIEvent(UIElement _sender, object _message);
        public Vector2 Position { get { return Parent != null ? Parent.Position + RelativePosition : RelativePosition; } }
        public Vector2 Size;

        public Vector2 RelativePosition;
        public Rectangle ElementRect { get { return new Rectangle((int)Position.X, (int)Position.Y, (int)Size.X, (int)Size.Y); } }
        public List<UIElement> Childs;
        public UIElement Parent;
        public bool IsActive = true;

        public UIElement(Vector2 _relativePosition)
        {
            RelativePosition = _relativePosition;
            Childs = new List<UIElement>();
        }

        public bool OverChild(Vector2 _pos)
        {
            if (!IsActive)
                return false;
            if (ElementRect.Contains(MathUtils.Vector2ToPoint(_pos)))
                return true;
            foreach (UIElement child in Childs)
            {
                if (child.OverChild(_pos))
                    return true;
            }
            return false;
        }

        public virtual void Update(GameTime _gameTime)
        {
            if (!IsActive)
                return;

            foreach (UIElement ele in Childs)
                ele.Update(_gameTime);
        }

        public virtual void Draw()
        {
            if (!IsActive)
                return;

            foreach (UIElement ele in Childs)
                ele.Draw();
        }
    }

    public class UIButton : UIElement
    {
        public event UIEvent ButtonPressed;
        public Texture2D textureUp;
        public Texture2D textureDown;
        public string Text;
        public bool IsDown { get; set; }

        public UIButton(string _text, string _upTexture, string _downTexture, Vector2 _relativePosition) : base(_relativePosition)
        {
            Text = _text;
            textureUp = GraphicsEngine.Instance.GetTexture(_upTexture);
            textureDown = GraphicsEngine.Instance.GetTexture(_downTexture);
            Size = new Vector2(textureUp.Width, textureDown.Height);
        }

        public UIButton(string _text, string _upTexture, string _downTexture, Vector2 _relativePosition, Vector2 _size)
            : base(_relativePosition)
        {
            Text = _text;
            textureUp = GraphicsEngine.Instance.GetTexture(_upTexture);
            textureDown = GraphicsEngine.Instance.GetTexture(_downTexture);
            Size = _size;
        }

        public UIButton(string _text, Texture2D _upTexture, Texture2D _downTexture, Vector2 _relativePosition, Vector2 _size)
            : base(_relativePosition)
        {
            Text = _text;
            textureUp = _upTexture;
            textureDown = _downTexture;
            Size = _size;
        }

        public override void Update(GameTime _gameTime)
        {
            if (!IsActive)
                return;

            if (ElementRect.Contains((int)InputHandler.MousePosition.X, (int)InputHandler.MousePosition.Y))
            {
                IsDown = true;

                if (InputHandler.LeftMouseUp() && IsDown)
                {
                    //IsDown = false;
                    if (ButtonPressed != null)
                        ButtonPressed(this, null);
                }
            }
            else
            {
                IsDown = false;
            }
            base.Update(_gameTime);       
        }

        public override void Draw()
        {
            if (!IsActive)
                return;
            if (IsDown)
            {
                GraphicsEngine.Instance.DrawGUITexture(textureDown, ElementRect, null, Color.White, Properties.LAYER_GUI_03);
            }
            else
            {
                GraphicsEngine.Instance.DrawGUITexture(textureUp, ElementRect, null, Color.White, Properties.LAYER_GUI_03);
            }
            GraphicsEngine.Instance.DrawString(Text, Position + Size / 2, Color.Black, TextAlignement.Centered, Properties.LAYER_GUI_02);
            base.Draw();
        }

        protected void FireButtonPressed(UIElement _sender, object _e)
        {
            if (ButtonPressed != null)
                ButtonPressed(_sender, _e);
        }
        
    }

    public class UI
    {

    }
}
